package com.starsky.websocket.controller;

import com.alibaba.fastjson.JSONObject;
import com.starsky.websocket.config.WebSocketConfig;
import com.starsky.websocket.domain.Result;
import com.starsky.websocket.handler.TextWebSocketHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @desc: 事件推送接口
 * @author: wangsh
 * @email: 1057718341@qq.com
 * @time: 2021/4/1 10:25
 */
@RestController
@Api(tags = "事件推送接口")
public class SendController {
    private static final Logger log = LoggerFactory.getLogger(SendController.class);
    @Autowired
    private WebSocketConfig webSocketConfig;

    /**
     * 改为可以接收OBJECT对象的json数据
     * 主要用于算法推送
     */
    @ApiOperation("事件推送接口")
    @PostMapping("/send2html")
    public Result<String> send(@RequestBody Map<String, Object> vehicles) {
        return sendByWS(vehicles);
    }

    /**
     * 推送实时数据到前端，用于人工判断是否设备异常
     */
    @ApiOperation("推送实时数据到前端")
    @PostMapping("/sendRealtime")
    public Result<String> sendRealtime(@RequestBody Map<String, Object> objs) {
        return sendByWS(objs);
    }

    @ApiOperation("推送实时数据到前端")
    @PostMapping("/sendByWS")
    private Result<String> sendByWS(@RequestBody Map<String, Object> objs) {

        log.info("收到数据：" + objs.toString());
        Result result = new Result(200, "推送成功", objs);
        //处理方式 1-多对多 2-点对点
        int nettyHandler = webSocketConfig.getNettyHandler();
        if (nettyHandler == 2) {
            pointTopoint(objs);
        } else {
            manyToMany(objs);
        }
        return result;
    }

    @ApiOperation("推送实时数据到前端")
    @PostMapping("/manyToMany")
    private Result<String> manyToMany(@RequestBody Map<String, Object> objs) {

        log.debug("收到数据：" + objs.toString());
        try {

            Object mainSectionId = objs.get("mainSectionId");
            if (mainSectionId == null) {
                mainSectionId = objs.get("roadSectionId").toString();
            }
            log.info("WS 客户端已连接，mainSectionId: " + mainSectionId);
//            Map<String, ChannelHandlerContext> ctxMap = WebSocketHandler.queue;
            Map<String, ChannelHandlerContext> ctxMap = TextWebSocketHandler.queue;
            log.info("WS 客户端连接queue通道数: " + ctxMap.size());
            if (ctxMap == null || ctxMap.size() <= 0) {
                log.info("WS 客户端未连接，推送失败,mainSectionId: " + mainSectionId);
                return new Result<String>(200, "请启动WS客户端 ...", objs.toString());
            }
            Iterator<Entry<String, ChannelHandlerContext>> it = ctxMap.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, ChannelHandlerContext> entry = it.next();
                log.info("WS 连接，Channel IP = " + entry.getKey() + ",roadSectionId: " + mainSectionId);
                entry.getValue().writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(objs)));
                log.info("WS 发送数据成功， Channel IP = " + entry.getKey() + ",roadSectionId:" + mainSectionId);
            }
        } catch (Exception e) {
            log.error(e.toString());
            return new Result<String>(500, "发送失败", objs.toString());
        }
        return new Result<String>(200, "发送成功", objs.toString());
    }


    @ApiOperation("点对点推送实时数据到前端")
    @PostMapping("/pointTopoint")
    private Result<String> pointTopoint(@RequestBody Map<String, Object> objs) {
        log.debug("收到数据：" + objs.toString());
        try {
            Object mainSectionId = objs.get("mainSectionId");
            if (mainSectionId == null) {
                mainSectionId = objs.get("roadSectionId").toString();
            }
            log.info("收到数据，mainSectionId: " + mainSectionId);
//            Map<String, ChannelHandlerContext> ctxMap = WebSocketHandler.queue;
            Map<String, ChannelHandlerContext> ctxMap = TextWebSocketHandler.queue;
            // chnnel->roadsection
            Map<String, String> sectionQueue = TextWebSocketHandler.section_queue;
            log.info("WS 客户端连接queue通道数: " + ctxMap.size());
            log.info("WS 客户端section_queue连接数: " + sectionQueue.size());

            if (ctxMap == null || ctxMap.size() <= 0) {
                log.info("WS 客户端未连接，推送失败,mainSectionId: " + mainSectionId);
                return new Result<String>(200, "请启动WS客户端 ...", objs.toString());
            }
            if (sectionQueue == null || sectionQueue.size() <= 0) {
                log.info("WS 客户端未携带参数roadSectionId连接，推送失败,mainSectionId: " + mainSectionId);
                return new Result<String>(200, "WS 客户端未携带参数roadSectionId连接 ...", objs.toString());
            }
            Iterator<Entry<String, ChannelHandlerContext>> it = ctxMap.entrySet().iterator();
            while (it.hasNext()) {
                Entry<String, ChannelHandlerContext> entry = it.next();
                String roadSectionId = sectionQueue.get(entry.getKey());
                if (roadSectionId == null) {
                    log.info("WS 未连接，Channel IP = " + entry.getKey() + ",roadSectionId:" + roadSectionId);
                    continue;
                }

                log.info("WS 连接，Channel IP = " + entry.getKey() + ",roadSectionId:" + roadSectionId + ",mainSectionId: " + mainSectionId);
                if (roadSectionId.equals(mainSectionId.toString())) {
                    entry.getValue().writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(objs)));
                    log.info("WS 发送数据成功， Channel IP = " + entry.getKey() + ",roadSectionId:" + roadSectionId);
                }
            }
        } catch (Exception e) {
            log.error(e.toString());
            return new Result<String>(500, "发送失败", objs.toString());
        }
        return new Result<String>(200, "发送成功", objs.toString());
    }

}
